#!/usr/bin/perl
# CCN::IPC::SingleInstance.pm
# Copyright (C) 2006, 2007  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

#
# For more information: http://carrierclass.net/
#

package CCN::IPC::SingleInstance;
use base qw(CCN::Class);

sub initialize
{
    my $self = shift;
    $self->{here} = shift; die ref($self)." needs here()" unless defined $self->{here};
    $self->{cmd}  = shift; die ref($self)." needs cmd()"  unless defined $self->{cmd};
}

sub here()  { shift->{here}; }
sub cmd()   { shift->{cmd};  }

sub last_touched($)
{
    my $self = shift;
    my $v = shift;
    $self->{last_touched} = $v if defined $v;
    return $self->{last_touched};
}

sub touch()
{
    my $self = shift;
    # Touch the "running" file
    open(my $run, '>', $self->here) or return 0;
    print $run $$;
    $self->last_touched( time() );
    return close($run) == 0;
}

sub killit()
{
    my $self = shift;
    open(my $run, '<', $self->here) or return 0;
    my $ps = <$run>;
    close($run);
    return if not defined $ps;
    $ps = int($ps);
    return unless $ps;
    kill 'TERM', $ps;
}

sub running()
{
    my $self = shift;
    my @running = stat $self->here;
    $self->last_touched( $running[9] );
}

sub restart()
{
    my $self = shift;
    $self->log_for('info','Request to restart '.ref($self));
    unlink $self->here;
    exec $self->cmd;
}

sub stop()
{
    my $self = shift;
    my $exit_code = shift;
    $exit_code = 0 if not defined $exit_code;
    
    unlink $self->here();
    eval { setpriority(0,0,1) };
    exit 0;
}

1;